from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, Request
from sqlalchemy.orm import Session
from database import get_db
from models import FlightRoute, User
from schemas import FlightRouteCreate, FlightRouteUpdate, FlightRouteSchema, ResponseModel, PaginatedResponse
from api.deps import get_current_active_user, get_current_superuser, get_client_ip
from utils import log_operation

router = APIRouter()

@router.get("", response_model=ResponseModel[PaginatedResponse[FlightRouteSchema]])
def get_flight_routes(
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(10, ge=1, le=100, description="每页数量"),
    name: Optional[str] = Query(None, description="航线名称搜索"),
    is_active: Optional[bool] = Query(None, description="激活状态过滤"),
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """获取航线列表"""
    query = db.query(FlightRoute)
    
    if name:
        query = query.filter(FlightRoute.name.contains(name))
    
    if is_active is not None:
        query = query.filter(FlightRoute.is_active == is_active)
    
    # 计算总数
    total = query.count()
    
    # 分页
    routes = query.order_by(FlightRoute.created_at.desc()).offset((page - 1) * page_size).limit(page_size).all()
    
    return ResponseModel(
        data=PaginatedResponse(
            total=total,
            page=page,
            page_size=page_size,
            items=routes
        )
    )

@router.get("/{route_id}", response_model=ResponseModel[FlightRouteSchema])
def get_flight_route(
    route_id: int,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """获取航线详情"""
    route = db.query(FlightRoute).filter(FlightRoute.id == route_id).first()
    if not route:
        raise HTTPException(
            status_code=404,
            detail="航线不存在"
        )
    
    return ResponseModel(data=route)

@router.post("", response_model=ResponseModel[FlightRouteSchema])
def create_flight_route(
    request: Request,
    route_in: FlightRouteCreate,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """创建航线"""
    ip_address = get_client_ip(request)
    
    try:
        # 检查航线名称是否已存在
        existing_route = db.query(FlightRoute).filter(FlightRoute.name == route_in.name).first()
        if existing_route:
            raise HTTPException(
                status_code=400,
                detail="航线名称已存在"
            )
        
        # 移除无人机检查 - 不再关联无人机
        
        # 检查航点数量
        if len(route_in.waypoints) < 2:
            raise HTTPException(
                status_code=400,
                detail="航线至少需要2个航点"
            )
        
        # 计算航线距离
        total_distance = calculate_route_distance(route_in.waypoints)
        
        # 将Waypoint对象转换为字典，以便JSON序列化
        waypoints_dict = [{
            "lat": wp.lat,
            "lng": wp.lng,
            "alt": wp.alt,
            # "name": wp.name
        } for wp in route_in.waypoints]
        
        # 创建航线
        db_route = FlightRoute(
            name=route_in.name,
            waypoints=waypoints_dict,
            distance=total_distance,
            description=route_in.description,
            created_by=current_user.id
        )
        
        db.add(db_route)
        db.commit()
        db.refresh(db_route)
        
        # 记录创建航线成功日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="create_route",
            operation_content=f"用户 {current_user.username} 创建航线：{route_in.name}（ID: {db_route.id}）",
            success=1
        )
        
        return ResponseModel(data=db_route)
    except HTTPException:
        db.rollback()
        # 记录创建航线失败日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="create_route",
            operation_content=f"用户 {current_user.username} 创建航线失败：{route_in.name}",
            success=0
        )
        raise
    except Exception as e:
        db.rollback()
        # 记录创建航线异常日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="create_route",
            operation_content=f"用户 {current_user.username} 创建航线异常：{route_in.name}，错误：{str(e)}",
            success=0
        )
        raise HTTPException(
            status_code=500,
            detail="创建航线过程中发生错误"
        )

@router.put("/{route_id}", response_model=ResponseModel[FlightRouteSchema])
def update_flight_route(
    request: Request,
    route_id: int,
    route_in: FlightRouteUpdate,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """更新航线信息"""
    ip_address = get_client_ip(request)
    
    try:
        route = db.query(FlightRoute).filter(FlightRoute.id == route_id).first()
        if not route:
            raise HTTPException(
                status_code=404,
                detail="航线不存在"
            )
        
        # 检查航线名称是否已存在（排除当前航线）
        if route_in.name and route_in.name != route.name:
            existing_route = db.query(FlightRoute).filter(FlightRoute.name == route_in.name).first()
            if existing_route:
                raise HTTPException(
                    status_code=400,
                    detail="航线名称已存在"
                )
        
        # 移除无人机检查 - 不再关联无人机
        
        # 检查航点数量
        if route_in.waypoints:
            if len(route_in.waypoints) < 2:
                raise HTTPException(
                    status_code=400,
                    detail="航线至少需要2个航点"
                )
            # 重新计算距离
            total_distance = calculate_route_distance(route_in.waypoints)
            route_in.distance = total_distance
        
        # 更新字段
        update_data = route_in.dict(exclude_unset=True)
        for field, value in update_data.items():
            setattr(route, field, value)
        
        db.commit()
        db.refresh(route)
        
        # 记录更新航线成功日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="update_route",
            operation_content=f"用户 {current_user.username} 更新航线：{route.name}（ID: {route_id}）",
            success=1
        )
        
        return ResponseModel(data=route)
    except HTTPException:
        db.rollback()
        # 记录更新航线失败日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="update_route",
            operation_content=f"用户 {current_user.username} 更新航线失败，航线ID: {route_id}",
            success=0
        )
        raise
    except Exception as e:
        db.rollback()
        # 记录更新航线异常日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="update_route",
            operation_content=f"用户 {current_user.username} 更新航线异常，航线ID: {route_id}，错误：{str(e)}",
            success=0
        )
        raise HTTPException(
            status_code=500,
            detail="更新航线过程中发生错误"
        )

@router.delete("/{route_id}", response_model=ResponseModel[dict])
def delete_flight_route(
    request: Request,
    route_id: int,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """删除航线"""
    ip_address = get_client_ip(request)
    
    try:
        route = db.query(FlightRoute).filter(FlightRoute.id == route_id).first()
        if not route:
            raise HTTPException(
                status_code=404,
                detail="航线不存在"
            )        
        
        route_name = route.name
        db.delete(route)
        db.commit()
        
        # 记录删除航线成功日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="delete_route",
            operation_content=f"用户 {current_user.username} 删除航线：{route_name}（ID: {route_id}）",
            success=1
        )
        
        return ResponseModel(data={"message": "航线删除成功"})
    except HTTPException:
        db.rollback()
        # 记录删除航线失败日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="delete_route",
            operation_content=f"用户 {current_user.username} 删除航线失败，航线ID: {route_id}",
            success=0
        )
        raise
    except Exception as e:
        db.rollback()
        # 记录删除航线异常日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="delete_route",
            operation_content=f"用户 {current_user.username} 删除航线异常，航线ID: {route_id}，错误：{str(e)}",
            success=0
        )
        raise HTTPException(
            status_code=500,
            detail="删除航线过程中发生错误"
        )

@router.put("/{route_id}/toggle_active", response_model=ResponseModel[FlightRouteSchema])
def toggle_route_active(
    request: Request,
    route_id: int,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
) -> Any:
    """切换航线激活状态"""
    ip_address = get_client_ip(request)
    
    try:
        route = db.query(FlightRoute).filter(FlightRoute.id == route_id).first()
        if not route:
            raise HTTPException(
                status_code=404,
                detail="航线不存在"
            )
        
        old_active_status = route.is_active
        # 切换激活状态
        route.is_active = not route.is_active
        
        db.commit()
        db.refresh(route)
        
        # 记录更新航线激活状态成功日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="toggle_route_active",
            operation_content=f"用户 {current_user.username} 切换航线激活状态：{route.name}（ID: {route_id}）从 {old_active_status} 变为 {route.is_active}",
            success=1
        )
        
        return ResponseModel(data=route)
    except HTTPException:
        db.rollback()
        # 记录更新航线状态失败日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="update_route_status",
            operation_content=f"用户 {current_user.username} 更新航线状态失败，航线ID: {route_id}，目标状态: {status}",
            success=0
        )
        raise
    except Exception as e:
        db.rollback()
        # 记录更新航线状态异常日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="update_route_status",
            operation_content=f"用户 {current_user.username} 更新航线状态异常，航线ID: {route_id}，错误：{str(e)}",
            success=0
        )
        raise HTTPException(
            status_code=500,
            detail="更新航线状态过程中发生错误"
        )



# 辅助函数：计算航线距离
def calculate_route_distance(waypoints: List) -> float:
    """计算航线总距离"""
    import math
    total_distance = 0.0
    
    for i in range(1, len(waypoints)):
        wp1 = waypoints[i-1]
        wp2 = waypoints[i]
        
        # 计算两点之间的欧氏距离
        # 同时支持对象和字典格式的航点数据
        try:
            # 尝试作为对象访问
            distance = math.sqrt(
                (wp2.lat - wp1.lat) ** 2 +
                (wp2.lng - wp1.lng) ** 2 +
                (wp2.alt - wp1.alt) ** 2
            )
        except AttributeError:
            # 尝试作为字典访问
            distance = math.sqrt(
                (wp2['lat'] - wp1['lat']) ** 2 +
                (wp2['lng'] - wp1['lng']) ** 2 +
                (wp2['alt'] - wp1['alt']) ** 2
            )
        
        total_distance += distance
    
    # 转换为千米并四舍五入到2位小数
    return round(total_distance * 111.32, 2)  # 简化的地球半径近似转换